/*
 * @author Chris
 * @since 2023/1/26 17:34
 *
 * @brief    The project will ...
 *
 * @note     {@link InitLcd1602()} init lcd by command 0x38, 0x0C, 0x06, 0x01
 *           {@link LcdWriteCmd()} write command.
 *           {@link LcdWaitReady()} wait lcd till it's not busy.
 *           {@link LcdShowStr()} show string content.
 *           {@link LcdSetCursor()} set address for beginning to input.
 *           {@link LcdWriteDat()} write data.
 *
 * @warning  Do not to ...
 *
 * Change Logs:
 *   Date           Author       Notes
 *   2023-01-26     Chris        the first version
 */

#include "reg51.h"

#define LCD1602_DB P0
#define LCD1602_RS  P1_0
#define LCD1602_RW  P1_1
#define LCD1602_E  P1_5

void InitLcd1602();

void LcdShowStr(unsigned int x, unsigned int y, unsigned char *str);

int main() {
    unsigned char str[] = "Kingst Studio";
    InitLcd1602();

    LcdShowStr(2, 0, str);
    LcdShowStr(0, 1, "Welcome to KST51");
    while (1);
}

void LcdWaitReady() {
    unsigned char stat;

    LCD1602_DB = 0xFF;  // 读取前需要先拉高
    LCD1602_RS = 0;
    LCD1602_RW = 1;
    do {
        LCD1602_E = 1;
        stat = LCD1602_DB;
        LCD1602_E = 0;
    } while (stat & 0x80);
}

void LcdWriteCmd(unsigned char cmd) {
    LcdWaitReady();
    LCD1602_RS = 0;
    LCD1602_RW = 0;
    LCD1602_DB = cmd;
    LCD1602_E = 1;  // 高脉冲
    LCD1602_E = 0;
}

void LcdWriteData(unsigned char dat) {
    LcdWaitReady();
    LCD1602_RS = 1;
    LCD1602_RW = 0;
    LCD1602_DB = dat;
    LCD1602_E = 1;
    LCD1602_E = 0;
}

void LcdSetCursor(unsigned int x, unsigned int y) {
    if (y == 0) {
        // 第一行
        LcdWriteCmd(0x80 | (0x00 + x));
    } else if (y == 1) {
        LcdWriteCmd(0x80 | (0x40 + x));
    } else {}
}

void LcdShowStr(unsigned int x, unsigned int y, unsigned char *str) {
    LcdSetCursor(x, y);
    while (*str != '\0') {
        LcdWriteData(*str++);
    }
}

void InitLcd1602() {
    LcdWriteCmd(0x38);  // 设置显示模式
    LcdWriteCmd(0x0C);  // 0b0000 1011 关显示、显示光标、光标产闪烁
    LcdWriteCmd(0x06);  // 0b0000 0110 指针、光标自动加/减 1、整屏不移动
    LcdWriteCmd(0x01);  // 0b0000 0001 清屏
}
